package com.example.demo.Service.lmp;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.Dto.*;

import com.example.demo.Mapper.GoodsMapper;
import com.example.demo.Service.GoodsService;
import com.example.demo.Util.ThreadLocallUtil;
import com.example.demo.VO.IPage;
import com.example.demo.VO.ProductInfoVo;
import com.example.demo.po.ProCateRel;
import com.example.demo.po.Product;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GoodsServicelmp extends ServiceImpl<GoodsMapper, Product> implements GoodsService {
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public ProductInfoVo getgoods(long productId) {
        String key = "goods:" + productId;
        Object o = redisTemplate.opsForValue().get(key);
        if (o != null) {
            String s = o.toString();
            if (s != null) {
                if (o=="商品不存在"){
                    throw new RuntimeException("商品不存在");
                }
                return JSONUtil.toBean(s, ProductInfoVo.class);
            }
        }
            ProductInfoVo getgoods = goodsMapper.getgoods(productId);
            if (getgoods == null) {
                redisTemplate.opsForValue().set("goods:" + productId,"商品不存在");
                throw new RuntimeException("商品不存在");
            }
            log.info("用户"+ ThreadLocallUtil.getUser().getUserId() +"查看商品"+ productId);
            redisTemplate.opsForValue().set("goods:" + productId, JSONUtil.toJsonStr(getgoods), ThreadLocalRandom.current().nextLong());
            return getgoods;

    }

    @Override
    public IPage categoryNamegetgoods(ListProductsDto ListProductsDto) {
        Map<Object, Object> entries = redisTemplate.opsForHash().entries("goods:" + ListProductsDto.getCategoryName());
        if (entries != null){
            List<Object> collect = entries.values().stream()
                    .skip((ListProductsDto.getPage() - 1) * ListProductsDto.getPageSize())
                    .limit(ListProductsDto.getPageSize())
                    .collect(Collectors.toList());
            List<ProductInfoVo> collect1 = collect.stream()
                .map(o -> JSONUtil.toBean(o.toString(), ProductInfoVo.class))
                .collect(Collectors.toList());
            IPage iPage = IPage.builder()
                    .records(collect1)
                    .total((long) entries.size())
                    .pages(1)
                    .size(ListProductsDto.getPageSize())
                    .current(ListProductsDto.getPage())
                    .build();
        }
        PageHelper.startPage(ListProductsDto.getPage(),ListProductsDto.getPageSize());
        List<ProductInfoVo> list = goodsMapper.list(ListProductsDto);
        if (list.size()==0||list==null){
            throw new RuntimeException("没有该类商品");
        }
        redisTemplate.opsForHash().putAll("goods:" + ListProductsDto.getCategoryName(), list.stream().collect(Collectors.toMap(ProductInfoVo::getId, ProductInfoVo::toString)));
        Page<ProductInfoVo> p = (Page<ProductInfoVo>) list;
        IPage iPage = IPage.builder()
                .records( list)
                .total(p.getTotal())
                .pages(p.getPages())
                .size(p.getPageSize())
                .current(p.getPageNum())
                .build();

        return iPage;
    }
    /**
     * 指定条件查询商品信息
     * @param searchProductsDto
     * @return
     */
    @Override
    public IPage searchgetgoods(SearchProductsDto searchProductsDto) {
        PageHelper.startPage(searchProductsDto.getPage(),searchProductsDto.getPageSize());
        List<ProductInfoVo> searchgetgoods = goodsMapper.searchlights(searchProductsDto);
        Page<ProductInfoVo> p = (Page<ProductInfoVo>) searchgetgoods;
        IPage iPage = IPage.builder()
                .pages(p.getPages())
                .total(p.getTotal())
                .records(searchgetgoods)
                .current(p.getPageNum())
                .size(p.getPageSize())
                .build();
        return iPage;
    }

    @Transactional
    @Override
    public void add(AddProductDto addProductDto) {
        int add = goodsMapper.add(addProductDto);
        if (add>0){
            redisTemplate.delete("goods");
            log.info("添加成功");
            return;
        }
        throw new RuntimeException("添加失败");
    }

    @Override
    @Transactional
    public void create(CreateProductDto createProductDto) {
        Product bean = BeanUtil.toBean(createProductDto, Product.class);
        Integer i = goodsMapper.batch1(bean);
    }

    @Transactional
    @Override
    public void batch(List<CreateProductDto> createProductDtos) {
        ArrayList<Object> objects = new ArrayList<>();
        for(CreateProductDto createProductDto:createProductDtos){
            Product bean = BeanUtil.toBean(createProductDto, Product.class);

            bean.setCreateTime(LocalDateTime.now());
            bean.setUpdateTime(LocalDateTime.now());
            objects.add(bean);
        }
        Integer batch = goodsMapper.batch(objects);
        if (batch>0){

            log.info("批量添加成功");
            return;
        }
        throw new RuntimeException("批量添加失败");
    }

    @Override
    @Transactional
    public void update(UpdateProductDto updateProductDto) {
        Product bean = BeanUtil.toBean(updateProductDto, Product.class);
        List<String> categories = updateProductDto.getCategories();
        //获取代理对象
        GoodsService currentProxy = (GoodsService) AopContext.currentProxy();
        // 使用代理对象调用方法,防止事务失效
        Product byId = currentProxy.getById(updateProductDto.getId());
        if (byId == null){
            throw new RuntimeException("商品不存在");
        }
        if (categories != null) {
            ArrayList<ProCateRel> objects = new ArrayList<>();
            for (String category : categories) {
                Long selectcategoryId = goodsMapper.selectcategoryId(category);
                if (selectcategoryId == null){
                    log.info("没有该商品种类"+ category);
                    throw new RuntimeException("没有该商品种类"+ category);
                }
                ProCateRel proCateRel = new ProCateRel(bean.getId(), selectcategoryId);
                objects.add(proCateRel);
            }
            Integer init = goodsMapper.init(objects);
            if (init<=0){
                throw new RuntimeException("商品"+updateProductDto.getId()+"添加失败");
            }
        }
        Integer update = goodsMapper.update(bean);
        if (update>0){
            redisTemplate.delete("goods"+updateProductDto.getId());
            log.info("商品"+updateProductDto.getId()+"修改成功");
            return;
        }

        throw new RuntimeException("商品"+updateProductDto.getId()+"修改失败");
    }
}
